package cn.thoughtworks.school.services;

import cn.thoughtworks.school.entities.Application;
import cn.thoughtworks.school.entities.User;
import cn.thoughtworks.school.exceptions.BusinessException;
import cn.thoughtworks.school.repositories.ApplicationRepository;
import cn.thoughtworks.school.response.SerialApplicationResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ApplicationService {
  @Autowired
  private ApplicationRepository applicationRepository;
  @Autowired
  private UserCenterService userCenterService;
  @Autowired
  private SubscriptionService subscriptionService;

  public void create(Application application, User user) {
    application.updateApplicant(user.getId());
    applicationRepository.save(application);
  }

  public PageImpl<SerialApplicationResponse> getMySerialsApplications(Long userId, String status, Pageable pageable) {
    Page<Map> serialApplicationResponses = getMySerialsApplicationsByStatus(userId, status, pageable);

    return new PageImpl(mergeApplicationsAndUsers(serialApplicationResponses), pageable, serialApplicationResponses.getTotalElements());
  }

  private Page<Map> getMySerialsApplicationsByStatus(Long userId, String status, Pageable pageable) {
    Long currentOrganizationId = userCenterService.getUserCurrentOrganizationId(userId);
    if ("申请中".equals(status)) {
      return applicationRepository.getMyNewSerialsApplications(currentOrganizationId, pageable);
    }
    return applicationRepository.getMyUnHandledSerialsApplications(currentOrganizationId, pageable);
  }

  private List<SerialApplicationResponse> mergeApplicationsAndUsers(Page<Map> serialApplicationResponses) {
    List<Map> applicationResponsesContent = serialApplicationResponses.getContent();
    List<Map> users = getUsers(applicationResponsesContent);
    return applicationResponsesContent.stream()
      .map(application -> {
        Map user = users.stream().filter(item -> Objects.equals(application.get("userId").toString(), item.get("id").toString()))
          .findFirst().get();
        return SerialApplicationResponse.build(application, user);
      })
      .collect(Collectors.toList());
  }

  private List<Map> getUsers(List<Map> serialApplicationResponses) {
    List<Long> userIds = serialApplicationResponses.stream()
      .map(item -> Long.parseLong(item.get("userId").toString()))
      .collect(Collectors.toList());

    return userCenterService.getUsersByIds(userIds);
  }

  @Transactional
  public void handling(Long authorizerId, String status, Long applicationId) throws BusinessException {
    Application application = updateApplicationStatus(applicationId, status);
    if ("已同意".equals(application.getStatus())) {
      subscriptionService.create(authorizerId, application);
    }
  }

  private Application updateApplicationStatus(Long applicationId, String status) throws BusinessException {
    Application application = getApplicationOrThrows(applicationId);
    application.handling(status);
    return applicationRepository.save(application);
  }

  private Application getApplicationOrThrows(Long applicationId) throws BusinessException {
    return applicationRepository.findById(applicationId).orElseThrow(() -> new BusinessException("不存在当前申请"));
  }

  public Page<Map> getApplications(Long id, Pageable pageable) {
    Page<Map> serialApplicationResponses = applicationRepository.getApplicationsUserId(id, pageable);
    return new PageImpl(mergeApplicationsAndUsers(serialApplicationResponses), pageable, serialApplicationResponses.getTotalElements());
  }
}
